﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;
using Chefbook.DataAccessLayer;
using Chefbook.UserActions;

namespace UnitTests.UserActionsTests
{
    [TestFixture]
    public class DeleteCategoryActionFixture
    {
        private MockRepository mocks;
        private IUserAction action;
        private Category root, testCategory, subCategory;
        private Recipe recipe, recipe1, recipe2;
        private ChefbookEntities db;

        [SetUp]
        public void Init()
        {
            mocks = new MockRepository();
            db = new ChefbookEntities();

            root = new Category();
            recipe = new Recipe();
            testCategory = new Category();
            subCategory = new Category();

            recipe1 = new Recipe();
            recipe2 = new Recipe();

            Assert.Contains(testCategory, recipe1.Categories.ToList());
            Assert.Contains(recipe1, testCategory.DirectRecipes.ToList());
            Assert.Contains(testCategory, recipe2.Categories.ToList());
            Assert.Contains(recipe2, testCategory.DirectRecipes.ToList());
            Assert.Contains(subCategory, testCategory.Subcategories.ToList());
            Assert.IsFalse(recipe.Categories.Contains(testCategory), "recipe.Categories.Contains(testCategory)");
            //The action should never change this
            Assert.IsFalse(testCategory.DirectRecipes.Contains(recipe), "testCategory.DirectRecipes.Contains(recipe)");
            Assert.True(root.DirectRecipes.Contains(recipe), "root.DirectRecipes.Contains(recipe)");

            action = new DeleteCategoryAction(testCategory) { DatabaseConnector = db };
        }

        [Test]
        public void DoActionTest()
        {
            var parent = testCategory.Parent;
            action.DoAction();
            Assert.IsFalse(root.Subcategories.Contains(testCategory), "Delete test failed");
            foreach (var rec in testCategory.DirectRecipes)
            {
                Assert.IsFalse(rec.Categories.Contains(testCategory), "Category not removed from all recipes");
            }
            //The action should never change this
            Assert.IsFalse(testCategory.DirectRecipes.Contains(recipe));
            Assert.True(root.DirectRecipes.Contains(recipe), "root.DirectRecipes.Contains(recipe)");
        }

        [Test]
        public void UndoActionTest()
        {
            var parent = testCategory.Parent;
            action.DoAction();
            action.UndoAction();
            Assert.True(parent.Subcategories.Contains(testCategory), "Delete test failed");
            foreach (var rec in testCategory.DirectRecipes)
            {
                Assert.True(rec.Categories.Contains(testCategory), "Category not removed from all recipes");
            }
            Assert.Contains(testCategory, recipe1.Categories.ToList());
            Assert.Contains(recipe1, testCategory.DirectRecipes);
            Assert.Contains(testCategory, recipe2.Categories.ToList());
            Assert.Contains(recipe2, testCategory.DirectRecipes);
            Assert.Contains(subCategory, testCategory.Subcategories.ToList());
            Assert.IsFalse(recipe.Categories.Contains(testCategory));
            //The action should never change this
            Assert.IsFalse(testCategory.DirectRecipes.Contains(recipe));
            Assert.True(root.DirectRecipes.Contains(recipe), "root.DirectRecipes.Contains(recipe)");
        }

        [Test]
        public void UndoActionWithoutDoingTest()
        {
            UserActionTestsHelper.UndoActionWithoutDoingTest(action);
        }

        [Test]
        public void UndoActionTwiceAfterDoingTest()
        {
            UserActionTestsHelper.UndoActionTwiceAfterDoingTest(action);
        }

        [Test]
        public void DoActionTwiceTest()
        {
            UserActionTestsHelper.DoActionTwiceTest(action);
        }

        [Test]
        public void ActionNameTest()
        {
            Assert.AreEqual(string.Format("Delete Category '{0}'",testCategory), action.ToString());
        }
    }
}
